package com.cictec.middleware.gps.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.cictec.middleware.commons.cache.ecache.EHCacheUtils;
import com.cictec.middleware.commons.utils.DateUtils;
import com.cictec.middleware.commons.utils.PMSUtils;
import com.cictec.middleware.core.entity.LineDeviatePlan;

/**
 * 偏线计算相关的服务
 * @author ql
 *
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@Service
public class DeviateService {

	private static Logger logger = LoggerFactory.getLogger(DeviateService.class);
	
	private static String CACHE_DEVIATE_PLAN = "bus-line-deviate-plan"; // 偏线计划
	
	@Autowired
	private RedisTemplate redisTemplate;
	
	/**
	 * 系统初始化加载
	 */
	public void init() {
		logger.info("【DeviateService】 初始化...");
		loadDeviatePlan(new Date());
	}
	
	/**
	 * 【缓存】【按天分组】加载当天偏线计划，清空缓存老数据
	 */
	public void loadDeviatePlan(){

		clearDeviatePlan(); 
		loadDeviatePlan(new Date());
	}

	/**
	 * 【缓存】【按天分组】加载指定日期偏线计划
	 * @param date
	 */
	public void loadDeviatePlan(Date date){
		logger.debug("【DeviateService】 加载 {} 偏线计划到缓存", DateUtils.formatDate(date));
		
		String cacheKey =  DateUtils.formatDate(date, "yyyyMMdd"); 
		List<LineDeviatePlan> lineDeviatePlanList = selectBusDeviatePlanByParams(null, date);
		EHCacheUtils.setValue(CACHE_DEVIATE_PLAN, cacheKey, lineDeviatePlanList);
		
//		lineDeviatePlanList = EHCacheUtils.getValue(CACHE_DEVIATE_PLAN, cacheKey);
	}
	
	/**
	 * 【缓存】清空缓存中偏线计划
	 */
	public void clearDeviatePlan(){
		logger.info("【DeviateService】 清空偏线计划缓存");
		try {
			EHCacheUtils.removeEhcache(CACHE_DEVIATE_PLAN);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 【缓存】重新加载偏线计划
	 * @param lineUuid
	 */
	public void reloadDeviatePlan(String lineUuid){
		
		clearDeviatePlan();
		loadDeviatePlan(new Date());
		logger.debug("【偏线计划信息】刷新线路 {} 偏线计划缓存信息" , lineUuid);
	}
	
	/**
	 * 【数据库】数据库加载偏线计划
	 * @param lineUuid
	 * @param date
	 * @return
	 */
	public List<LineDeviatePlan> selectBusDeviatePlanByParams(String lineUuid, Date date){
		HashOperations<String, String, List<LineDeviatePlan>> ops = redisTemplate.opsForHash();
		if(redisTemplate.hasKey(CACHE_DEVIATE_PLAN)){
			List<LineDeviatePlan> list = new ArrayList<>();
			if(lineUuid == null){
				Set<String> lineUuids = ops.keys(CACHE_DEVIATE_PLAN);
				for (String _lineUuid : lineUuids) {
					list.addAll(ops.get(CACHE_DEVIATE_PLAN, _lineUuid));
				}
			}else{
				list = ops.get(CACHE_DEVIATE_PLAN, lineUuid);
			}
			return list;
			
		}
		return new ArrayList<>();
	}
	
	
	/**
	 * 根据时间段，获取偏线计划
	 * @param lineUuid
	 * @param lineType
	 * @param startTime	趟次开始时间
	 * @param endTime	趟次结束时间
	 * @return
	 */
	public List<LineDeviatePlan> getDeviatePlanByTimeSegment(String lineUuid, String lineType, Date startTime, Date endTime){
		
		String cacheKey =  DateUtils.formatDate(endTime, "yyyyMMdd"); 
		List<LineDeviatePlan> lineDeviatePlanList = EHCacheUtils.getValue(CACHE_DEVIATE_PLAN, cacheKey);
		if(lineDeviatePlanList == null){
			loadDeviatePlan(endTime);
			lineDeviatePlanList = EHCacheUtils.getValue(CACHE_DEVIATE_PLAN, cacheKey);
		}
		
				
		List<LineDeviatePlan> rtList = new ArrayList<LineDeviatePlan>();
		for (LineDeviatePlan dp : lineDeviatePlanList) {
			
			if(dp.getLdpLineUuid().equals(lineUuid)
					&& dp.getLdpLineType().equals(lineType)
					&& dp.getLdpStatus().equals("1")	// 启动的
					&& ((dp.getLdpStartTime().getTime() <= startTime.getTime() && dp.getLdpEndTime().getTime() >= startTime.getTime())		// 位于开始时间两侧
							|| (dp.getLdpStartTime().getTime()) <= endTime.getTime() && dp.getLdpEndTime().getTime() >= endTime.getTime()	// 位于结束时间两侧
							|| (dp.getLdpStartTime().getTime()) >= startTime.getTime() && dp.getLdpEndTime().getTime() <= endTime.getTime() // 介于开始、结束之间
							)
					){
				
				rtList.add(dp);
			}
		}
		
		
		return rtList;
	}
	
	/**
	 * 根据时间和当前站的序号判断是否在偏线计划区域。
	 * @param lineUuid		 线路uuid 【必填】
	 * @param lineType 		  线路类型 【必填】
	 * @param time			 位置点上传时间【必填】
	 * @param stationSequence 站点序号【不存在的时候，默认不进入判定】
	 * @return false:未在偏线计划内，true：在偏线计划内
	 */
	public boolean isInDeviatePlan(String lineUuid,String lineType,Date time, Integer stationSequence){
		if(stationSequence == null || stationSequence == 0){
			return false;
		}
		
		String cacheKey =  DateUtils.formatDate(time, "yyyyMMdd"); 
		List<LineDeviatePlan> lineDeviatePlanList = EHCacheUtils.getValue(CACHE_DEVIATE_PLAN, cacheKey);
		if(lineDeviatePlanList == null){
			loadDeviatePlan(time);
			lineDeviatePlanList = EHCacheUtils.getValue(CACHE_DEVIATE_PLAN, cacheKey);
		}
		
		
		for (LineDeviatePlan dp : lineDeviatePlanList) {
			
			if(dp.getLdpLineUuid().equals(lineUuid)
					&& dp.getLdpLineType().equals(lineType)
					&& dp.getLdpStatus().equals("1")	// 启动的
					&& dp.getLdpStartTime().getTime() < time.getTime() && dp.getLdpEndTime().getTime() >= time.getTime()
					&& !PMSUtils.isEmpty(dp.getStartStationSequence()) && !PMSUtils.isEmpty(dp.getEndStationSequence())		// 添加此条件的原因：线路站点做了变更，而偏线计划里边的没有更新
					&& dp.getStartStationSequence() <= stationSequence && dp.getEndStationSequence() >= stationSequence){
				return true;
			}
		}

		return false;
	}
	
	
	
}
